// 定义蛇的类snake
class Snake {
  // 表示蛇头的元素
  head: HTMLElement;
  // 表示蛇身的元素
  body: HTMLCollection;
  // 表示蛇的元素
  snake: HTMLElement;

  constructor() {
    this.snake = document.getElementById('snake')!;
    this.head = document.querySelector('#snake > div') as HTMLElement; // 类型断言
    this.body = this.snake.getElementsByTagName('div');
  }

  // 获取蛇头的x坐标
  get X () {
    return this.head.offsetLeft;
  }
  // 获取蛇头的y坐标
  get Y () {
    return this.head.offsetTop;
  }

  // 设置蛇头的x坐标
  set X (value: number) {
    // 如果新值 和 旧值相同,怎么直接返回
    if (this.X === value) return;

    // 修改x时,是在修改水平坐标,蛇在左右移动,蛇向左移动,不能向右掉头
    if (this.body[1] && (this.body[1] as HTMLElement).offsetLeft === value ) {
      if (value > this.X) {
        // 如果新值value大于旧值X,则说明蛇在向右走,此时发生掉头,应该使蛇继续向左走
        value = this.X - 10
      } else {
        value = this.X + 10
      }
    }

    // X的值范围 0-290
    if (value < 0 || value > 290) {
      // 进入判断则说明蛇撞墙了
      throw new Error('蛇撞墙了!')
    }

    this.moveBody();

    this.head.style.left = value + 'px';
    this.checkHeadBody();
  }
  // 设置蛇头的y坐标
  set Y (value: number) {
    // 如果新值 和 旧值相同,怎么直接返回
    if (this.Y === value) return;

    if (this.body[1] && (this.body[1] as HTMLElement).offsetTop === value) {
      if (value > this.Y) {
        value = this.Y - 10
      } else {
        value = this.Y + 10
      }
    }

    // Y的值范围 0-290
    if (value < 0 || value > 290) {
      // 进入判断则说明蛇撞墙了
      throw new Error('蛇撞墙了!')
    }

    this.moveBody();

    this.head.style.top = value + 'px';
    this.checkHeadBody();
  }

  // 增加蛇的长度
  addBody() {
    // 向蛇元素添加div元素
    this.snake.insertAdjacentHTML("beforeend", "<div></div>")
  }
  // 蛇身移动
  moveBody() {
    // 将后面的身体设置为前面的身体的位置
    // 遍历获取所有的身体
    for (let i = this.body.length - 1; i > 0; i--) {
      // 获取前面身体的位置
      let X = (this.body[i - 1] as HTMLElement).offsetLeft;
      let Y = (this.body[i - 1] as HTMLElement).offsetTop;

      // 将值设置到当前身体位置
      (this.body[i] as HTMLElement).style.left = X + 'px';
      (this.body[i] as HTMLElement).style.top = Y + 'px';
    }
  }

  checkHeadBody() {
    // 获取所有的身体,检查蛇头是否和蛇身坐标重叠
    for (let i = 1; i < this.body.length; i++) {
      let bd = this.body[i] as HTMLElement
      if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
        // 进入判断说明,蛇头撞到了身体
        throw new Error('撞到了自己!')
      }
    }
  }

}

export default Snake;